package com.shanghaionstar.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import com.onstar.cn.api.VehicleService;
import com.onstar.cn.common.exception.HttpException;
import com.onstar.cn.common.log.LogManager;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.common.util.PreferencesUtls;
import com.onstar.cn.framework.annotation.http.HeadsValue;
import com.onstar.cn.framework.annotation.http.Request;
import com.onstar.cn.framework.network.entity.RequestEntity;
import com.onstar.cn.framework.network.enumtype.HttpAccept;
import com.onstar.cn.framework.network.enumtype.HttpMethod;
import com.onstar.cn.framework.network.enumtype.Language;
import com.onstar.cn.framework.network.http.ResponseHandler;
import com.onstar.cn.framework.network.http.Sender;
import com.onstar.cn.framework.utils.GsonHelper;
import com.onstar.cn.framework.utils.RxBus;
import com.onstar.cn.mag.enumtype.RemoteCommandsType;
import com.onstar.cn.rxconstants.RxConstants;
import com.onstar.cn.sqlite.entities.PollingEntity;
import com.onstar.cn.vehicle.R;
import com.onstar.cn.vehicle.entity.ErrorEnum;
import com.onstar.cn.vehicle.entity.ErrorInfo;
import com.onstar.cn.vehicle.entity.RequestStatus;
import com.onstar.cn.vehicle.result.PollingResult;
import com.onstar.cn.vehicle.result.ResultHandler;
import com.onstar.cn.vehicle.service.VehicleDBService;
import com.shanghaionstar.OnstarApplication;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author 6335yz
 * @ClassName: VehiclePollingService
 * @Description: 轮训service，对inprogress command进行轮训,结果通过实现了IResultService接口的类返回
 * @date 2015年8月27日 下午8:03:38
 */
public class VehiclePollingService extends Service {
    private LogManager log;
    private ResultHandler resultHandler;
    private PollingEntity entity;
    private VehicleDBService dbService;
    private PollingEntity currentPollingEntity;
    private boolean isAllowPolling = false;
    private Timer timer;
    private String serverURL;
    private TimerTask task;

    private String completeTime;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        isAllowPolling = true;
        log = LogManager.getInstance(this);
        resultHandler = ResultHandler.getInstance(this);
        dbService = new VehicleDBService(this, OnstarApplication.getmDbUtils());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null && intent.getSerializableExtra("pollingEntity") != null) {
            isAllowPolling = true;
            entity = (PollingEntity) intent.getSerializableExtra("pollingEntity");
            serverURL = intent.getStringExtra(Constants.SERVER_URL);
            if (task != null) {
                task.cancel();
                task = null;
            }
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
            timer = new Timer();
            task = new TimerTask() {
                @Override
                public void run() {
                    log.d(">>>>>>>>>>>>>>>>service start.<<<<<<<<<<<<<<<<<<");
                    pollingVehicleStatus();
                }
            };
            timer.schedule(task, Constants.POLLING_TIMER_TIME_START, Constants.POLLING_TIMER_TIME_INTERVAL);
        } else {
            stopSelf();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    public PollingEntity getPollingEntityFromDB() {
        List<PollingEntity> list = dbService.getInprogressPollingStatus(entity.getVin());
        if (list != null && list.size() != 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    private void processError(String code, String description) {
        log.i("pollingVehicleStatus Failure the code is---------->" + code + " ---and the error description is ---->"
                + description);
        currentPollingEntity.setRequestStatus(RequestStatus.Failure.getStringValue());
        dbService.updatePollingStatus(currentPollingEntity);

        PollingResult result = new PollingResult();
        ErrorInfo errorInfo = new ErrorInfo();
        errorInfo.setCode(code);
        errorInfo.setMsg(description);
        result.setErrorInfo(errorInfo);
        result.setRequestType(currentPollingEntity.getRequestType());
        result.setRequestStatus(RequestStatus.Failure.getStringValue());
        result.setRequestId(currentPollingEntity.getRequestId());
        result.setCompleteTime(completeTime);
//		resultHandler.onResult(result);
        /**
         * 使用rx发送
         */
        sendResult(result);
        isAllowPolling = true;
        stopAll();
    }

    private void processHttpError(HttpException httpException) {
        log.i("pollingVehicleStatus httpException Failure");
        currentPollingEntity.setRequestStatus(RequestStatus.Failure.getStringValue());
        dbService.updatePollingStatus(currentPollingEntity);

        PollingResult result = new PollingResult();
//		ErrorInfo errorInfo = new ErrorInfo();
//		errorInfo.setCode(code);
//		errorInfo.setMsg(description);
//		result.setErrorInfo(errorInfo);
        result.setRequestType(currentPollingEntity.getRequestType());
        result.setRequestStatus(RequestStatus.Failure.getStringValue());
        result.setHttpException(httpException);
        result.setRequestId(currentPollingEntity.getRequestId());
//		resultHandler.onResult(result);
        /**
         * 使用rx发送
         */
        sendResult(result);
        isAllowPolling = true;
    }


    private void processInProgress() {
        log.i("processInProgress()  --------->>polling service in progress");
        long duration = System.currentTimeMillis() - Long.valueOf(currentPollingEntity.getStartTime());
        if (duration > Constants.REMOTE_DURATION_TIME) {
            String desc = "";
            if (RemoteCommandsType.COMMANDS_LOCATION.value().equalsIgnoreCase(currentPollingEntity.getRequestType())) {
                desc = getString(R.string.get_vehicleLocation_error);
            } else {
                desc = getString(R.string.remote_control);
            }
            processError(ErrorEnum.SOMP_906.getStringValue(), desc);
        }
        isAllowPolling = true;
    }

    private void processSuccess(JSONObject commandResponse, String requestId, String json) throws Exception {
        String bodyJson = json;
        log.i("processSuccess()  --------->>polling service success");
        currentPollingEntity.setRequestStatus(RequestStatus.Success.getStringValue());
        currentPollingEntity.setEndTime(System.currentTimeMillis() + "");
        dbService.updatePollingStatus(currentPollingEntity);

        String requestType = commandResponse.getString("type");
        String completeTime = commandResponse.getString("completionTime");
        PollingResult pollingResult = new PollingResult();
        pollingResult.setRequestId(requestId);
        pollingResult.setCompleteTime(completeTime);
        pollingResult.setMsgTarget(Constants.SERVICE_RESPONSE_SUCCESS);
        pollingResult.setRequestType(requestType);
        pollingResult.setRequestStatus(RequestStatus.Success.getStringValue());
        if (RemoteCommandsType.COMMANDS_LOCATION.value().equals(requestType)) {
            JSONObject body = commandResponse.getJSONObject("body");
            JSONObject location = body.getJSONObject("location");
            String lat = location.getString("lat");
            String lon = location.getString("long");
            pollingResult.setLat(lat);
            pollingResult.setLon(lon);
        } else if (RemoteCommandsType.COMMANDS_DIAGNOSTICS.value().equals(requestType)) {
            bodyJson = commandResponse.getString("body");
        }
        pollingResult.setJson(bodyJson);
//		resultHandler.onResult(pollingResult);
        /**
         * 使用rx发送
         */
        sendResult(pollingResult);
        isAllowPolling = true;
        stopAll();
    }

    public void pollingVehicle(){

    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.GET)
    public void pollingVehicleStatus() {
        if (isAllowPolling) {
            isAllowPolling = false;
            currentPollingEntity = getPollingEntityFromDB();
            if (currentPollingEntity != null) {
                VehicleService service = new VehicleService(serverURL);
                RequestEntity requestEntity = new RequestEntity();
                LinkedHashMap<String, Object> customHeads = new LinkedHashMap<String, Object>();
                customHeads.put("Authorization", entity.getToken());
                requestEntity.setCustomHeads(customHeads);
                service.pollingVehicleStatus(requestEntity, currentPollingEntity.getVin(),
                        currentPollingEntity.getRequestId());
                Sender sender = new Sender();
                sender.send(requestEntity, new ResponseHandler() {
                    @Override
                    public void onSuccess(String tag, String json) {
                        log.d("pollingVehicleStatus onSuccess() -------------->>" + json);
                        JSONObject commandResponse = GsonHelper.getJsonObject(json, "commandResponse");
                        JSONObject error = GsonHelper.getJsonObject(json, "error");
                        if (commandResponse != null) {
                            try {
                                String status = commandResponse.getString("status");
                                if (commandResponse.has("completionTime")) {
                                    completeTime = commandResponse.getString("completionTime");
                                }
                                if (RequestStatus.Success.getStringValue().equalsIgnoreCase(status)) {
                                    processSuccess(commandResponse, currentPollingEntity.getRequestId(), json);
                                } else if (RequestStatus.InProgress.getStringValue().equalsIgnoreCase(status)) {
                                    processInProgress();
                                } else if (RequestStatus.Failure.getStringValue().equalsIgnoreCase(status)) {
                                    JSONObject body = commandResponse.getJSONObject("body");
                                    JSONObject errorBody = body.getJSONObject("error");
                                    processError(errorBody.getString("code"), errorBody.getString("description"));
                                } else if (RequestStatus.Pending.getStringValue().equalsIgnoreCase(status)) {
                                    // pending ?
                                    processInProgress();
                                } else if (error != null) {
                                    String code = error.getString("code");
                                    String description = error.getString("description");
                                    processError(code, description);
                                }
                            } catch (Exception e) {
                                log.e(e.getMessage());
                                processError(ErrorEnum.VEHICLE_EXCEPTION.getStringValue(), e.getMessage());
                            }
                        } else if (error != null) {
                            try {
                                String code = error.getString("code");
                                String description = error.getString("description");
                                processError(code, description);
                            } catch (JSONException e) {
                                processError(ErrorEnum.VEHICLE_EXCEPTION.getStringValue(), e.getMessage());
                            }
                        }
                    }

                    @Override
                    public void onError(String tag, HttpException e) {
                        log.d(e.getMessage());
                        processHttpError(e);
                    }
                }, getClass(), "pollingVehicleStatus");
            } else {
                // no request need to polling
                stopSelf();
            }
        }
    }

    public void stopAll() {
        if (task != null) {
            task.cancel();
        }
        if (timer != null) {
            timer.cancel();
        }
        stopSelf();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (task != null) {
            task.cancel();
        }
        if (timer != null) {
            timer.cancel();
        }
        log.d("service destory.");
    }

    private void sendResult(PollingResult pollingResult) {
        RemoteCommandsType commandsType = RemoteCommandsType.fromValue(pollingResult.getRequestType());
        int action = 0;
        switch (commandsType) {
            case COMMANDS_LOCK_DOOR:
            case COMMANDS_UNLOCK_DOOR:
            case COMMANDS_START:
            case COMMANDS_CANCEL_START:
            case COMMANDS_ALERT:
                action = RxConstants.REMOTE_PAGE;
                break;
            case COMMANDS_LOCATION:
                action = RxConstants.VEHICLE_LOCATE;
                break;
            case COMMANDS_GEOFENCE_LOCATION:
                action = RxConstants.VEHICLE_LOCATE;
                break;
            case COMMAND_DISABLEHOTSPOT:
            case COMMAND_ENSABLEHOTSPOT:
            case COMMAND_GETHOTSPOTINFO:
            case COMMAND_GETHOTSPOTSTATUS:
            case COMMAND_SETHOTSPOTINFO:
                action = RxConstants.WIFI_HOTSPOT;
                break;
            case COMMAND_GETCHARGINGPROFILE:
            case COMMAND_SETCHARGINGPROFILE:
            case COMMAND_GETCOMMUTESCHEDULE:
            case COMMAND_SETCOMMUTESCHEDULE:
                action = RxConstants.MORE_PAGE;
                break;
            case COMMANDS_DIAGNOSTICS:
                action = RxConstants.HOME_PAGE;
                break;
            case COMMANDS_TBT_ROUTE:
                break;
            case COMMANDS_NAV_DESTINATION:
                break;
            default:
                break;
        }

        //纪录成功请求次数
        if (pollingResult != null && pollingResult.getRequestStatus().equalsIgnoreCase(RequestStatus.Success.getStringValue())) {
            int count = PreferencesUtls.getInstance(this).getInt(Constants.HIGH_PRAISE, 0);
            PreferencesUtls.getInstance(this).putInt(Constants.HIGH_PRAISE, count + 1);
            if (PreferencesUtls.getInstance(this).getInt(Constants.HIGH_PRAISE, 0) >= 3) {
                RxBus.getDefault().post(RxConstants.HIGH_PRAISE, "show");
                PreferencesUtls.getInstance(this).putInt(Constants.HIGH_PRAISE, 0);
            }
        }

        //test
        action = RxConstants.ALL_PAGE_ALERT;
        if (action != 0) {
            RxBus.getDefault().post(action, pollingResult);
        }
    }
}

